﻿using System;
using Newtonsoft.Json;
using T.FAS.Runtime.DataModel.Dao;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.FAS.Runtime.Metadata.Entity;
using T.FAS.Runtime.Base.Entity;
using System.Collections.Generic;
using System.Transactions;

namespace T.FAS.Runtime.DataModel.Plugin
{
    public class DataObjectRTPManager : AbsRTPMetaDataManager
    {
        /// <summary>
        /// 改为virtual，方便StaticDataObjectManager重写
        /// </summary>
        protected virtual DataObjectLogic DataObjectLogic { get; set; } = new DataObjectLogic();
        protected virtual DatabaseLogic DatabaseLogic { get; set; } = new DatabaseLogic();

        public virtual string MetaDataID => "DataObject";
        public virtual string MetaDataName => "数据对象";

        public override IMetaDataContent GetMetaDataContent(string metaDataId)
        {
            try
            {
                if (string.IsNullOrEmpty(metaDataId))
                    throw new FasException(DataModelErrorCode.DO.RetrieveError, $"{MetaDataName}id为空");
                var dataobject = DataObjectLogic.GetDataObjectByID(metaDataId);
                if (dataobject == null)
                {
                    throw new FasException(DataModelErrorCode.DO.RetrieveError, $"{MetaDataName}:{metaDataId}不存在，请检查!");
                }

                dataobject.MetaDataID   = dataobject.ID;
                dataobject.MetaDataCode = dataobject.Code;
                dataobject.MetaDataName = dataobject.Name;
                return dataobject;
            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.DO.RetrieveError, $"获取{MetaDataName}元数据失败", e);
            }
        }

        public override string SerializeObject(IMetaDataContent metadata, MetadataSerializeType serializeType)
        {
            if (serializeType == MetadataSerializeType.JSON)
            {
                //(metadata as DataObject).ClearRef();
                return JsonConvert.SerializeObject(metadata, new JsonSerializerSettings
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                });
            }
            else
            {
                throw new NotImplementedException();
            }
        }

        public override IMetaDataContent DeserializeObject(string metaDataString, MetadataSerializeType serializeType)
        {
            if (serializeType == MetadataSerializeType.JSON)
            {
                return DeserializeObject(metaDataString, true);
            }
            else
            {
                throw new NotImplementedException();
            }
        }

        public override IMetaDataContent DeserializeObject(string metaDataString, bool isPackingData = false)
        {
            if (string.IsNullOrEmpty(metaDataString))
                throw new FasException(DataModelErrorCode.Error, $"DO反序列化Json不能为空，请检查！");
            var cdo = JsonConvert.DeserializeObject<DataObject>(metaDataString, new JsonSerializerSettings
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            });

            if (isPackingData)
                PackagingDependencyMetaData(cdo);

            return cdo;
        }

        private void PackagingDependencyMetaData(IMetaDataContent metaData)
        {
            var dataObject = metaData as DataObject;
            if (dataObject.Database == null)
                dataObject.Database = DatabaseLogic.GetDatabaseByID(dataObject.DatabaseID);
            if (dataObject.Database == null)
            {
                var unifyCode = $"元数据类型{DataModelConst.DOMetaType}的元数据Code:{dataObject.Code},ID:{dataObject.ID}";
                throw new FasException(DataModelErrorCode.DO.InitError, $"{unifyCode}的DB:{dataObject.DatabaseID}不存在");
            }
        }


        public override void Import(List<IMetaDataContent> contents)
        {
            var dataObjectList = new List<DataObject>();
            foreach (var metaData in contents)
            {
                var dataObject = metaData as DataObject;
                if (dataObject == null)
                {
                    throw new FasException(DataModelErrorCode.DO.ImportError, $"元数据类型不是{MetaDataID}, 实际类型:" + metaData.GetType().FullName);
                }

                dataObjectList.Add(dataObject);
            }
            try
            {

                using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }))
                {
                    foreach (var dataObject in dataObjectList)
                    {
                        DataObjectLogic.DeleteDataObject(dataObject.MetaDataID);
                        DataObjectLogic.SaveDataObject(dataObject);
                    }

                    scope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.DO.ImportError, $"{MetaDataID}元数据导入失败", e);
            }
        }

        /// <summary>
        /// 导入前执行方法
        /// </summary>
        public void PreImportFunc(List<IMetaDataContent> metaDatas)
        {
            //TODO 数据对象对应的表结构同步
            //Implemented 在目标环境同步表元数据，一定要放在DO元数据导入之前做，否则找不到DO变更差异
            new DataObjectMetaManagerFactory().Build().Sync(metaDatas);
        }

        public override void Delete(List<string> IDs)
        {
            if (IDs == null)
                return;
            IDs = IDs.Where(id => id != null).ToList();
            try
            {

                using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }))
                {
                    foreach (var Id in IDs)
                    {
                        DataObjectLogic.DeleteDataObject(Id);
                    }
                    scope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.DO.ImportError, $"{MetaDataID}元数据导入失败", e);
            }
        }

        public override IRefSchemaEntity BuildRefSchema(IMetaDataContent metaDataContent)
        {
            if (metaDataContent is DataObject @do)
            {
                return @do.BuildRefSchema();
            }
            else
            {
                throw new ArgumentNullException(nameof(metaDataContent));
            }
        }

        public override IEnumerable<Metadata.Entity.Term> BuildTerms(IMetaDataContent metaDataContent, IEnumerable<Metadata.Entity.Term> termList = null)
        {
            return default;
        }

        public override IRefSchemaEntity DeserializeRefSchemaEntity(string schemaEntityJson)
        {
            return JsonConvert.DeserializeObject<DataObjectRefSchemaEntity>(schemaEntityJson);
        }
    }
}
